#include "net_proto_recorder.h" 
#include <chrono> 
#include "filepath.h"
#include "file_util.h"

bool CSyncOneMsgBinary::doRecord(int type, const char* data, int len) {
    m_id++;
    auto sendPhth = SigNetProtoRecoder.getRecvMsgPath(m_folder.c_str(), m_id, type, len);
    SigNetProtoRecoder.syncSave(sendPhth.c_str(), data, len);
    return true;
}

bool COneFixedAppendBinary::doRecord(const char* data, int len) {
    std::string path;
    if (m_total + len > m_max) {
        auto f1 = m_max - m_total;
        if (f1 > 0) {
            path = SigNetProtoRecoder.getSendMsgPath(m_fodler.c_str(), 0, 0, m_index);
            SigNetProtoRecoder.syncSaveAppend(path.c_str(), (char*)data, (int)f1);
        }
        auto f2 = len - f1;
        if (f2 > 0) {
            m_index++;
            path = SigNetProtoRecoder.getSendMsgPath(m_fodler.c_str(), 0, 0, m_index);
            SigNetProtoRecoder.syncSaveAppend(path.c_str(), ((char*)data) + f1, (int)f2);
        }
        m_total = f2;
    } else {///直接写
        path = SigNetProtoRecoder.getSendMsgPath(m_fodler.c_str(), 0, 0, m_index);
        SigNetProtoRecoder.syncSaveAppend(path.c_str(), (char*)data, len);
        m_total += len;
    }
    return true;
}

bool CSyncMsgLength::doRecord(int len) {
    auto msglenpath = SigNetProtoRecoder.getSendMsgPath(m_folder.c_str(), 0, 0, 0);
    CFileUtil fu;
    fu.openFile(msglenpath.c_str(), "a+");
    char buf4len[16] = {0};
    sprintf_s(buf4len, sizeof(buf4len), "%d\n", len);
    fu.appendWrite(buf4len, strlen(buf4len));
    return true;
}

int32_t CNetProtoRecorder::syncLoad(const char* path, char* data, int32_t max_size) {
    std::ifstream infile;
    infile.open(path, std::ios::binary | std::ios::in);
    if (!infile.good()) {
        std::cout << "load_binary_file_sync path not good (" << path << ")" << std::endl;
        return -1;
    }
    infile.seekg(0, std::ios::end);
    auto length = infile.tellg();
    infile.seekg(0, std::ios::beg);
    if (max_size < length) {
        std::cout << "(max_size<length)max_size(" << max_size << ")" << "length(" << length << ")" << std::endl;
        return -1;
    }
    infile.read(data, length);
    infile.close();
    return (int32_t)length;
}

int32_t CNetProtoRecorder::syncSave(const char* path, const char* data, int32_t max_size) {
    std::ofstream file(path, std::ios::out | std::ios::binary);
    if (file.good()) {
        file.write(data, max_size);
        file.flush();
        file.close();
        return max_size;
    } else {
        std::cout << "save_binary_file_sync path not good (" << path << ")" << std::endl;
    }
    return -1;
}

int32_t CNetProtoRecorder::syncSaveAppend(const char* path, const char* data, int32_t max_size) {
    std::ofstream file(path, std::ios::app | std::ios::binary);
    if (file.good()) {
        file.write(data, max_size);
        file.flush();
        file.close();
        return max_size;
    } else {
        std::cout << "save_binary_file_sync path not good (" << path << ")" << std::endl;
    }
    return -1;
}

std::string CNetProtoRecorder::getRecvMsgPath(const std::string& strFolder, uint64_t uid, int type, int len) {
    char buf[1024] = {0};
    filepath fp;
    auto cur = fp.get_current_dir();
    auto connect = fp.concat_paths(cur, filepath(strFolder + "\\"));
    if (!connect.directory_exists()) {
        connect.create_directories_recursively();
    }
    sprintf_s(buf, sizeof buf, "%sRecv_%llu_type_%d_len_%d.msg", connect.c_str(), uid, type, len);
    return std::string(buf);

}

std::string CNetProtoRecorder::getSendMsgPath(const std::string& strFolder, uint64_t uid, int type, int len) {
    char buf[1024] = {0};
    filepath fp;
    auto cur = fp.get_current_dir();
    auto connect = fp.concat_paths(cur, filepath(strFolder + "\\"));
    if (!connect.directory_exists()) {
        connect.create_directories_recursively();
    }
    sprintf_s(buf, sizeof buf, "%sSend_%llu_type_%d_len_%d.msg", connect.c_str(), uid, type, len);
    return std::string(buf);
}

uint64_t CNetProtoRecorder::getMsNow() {
    auto time_now = std::chrono::system_clock::now();
    auto duration_in_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_now.time_since_epoch());
    return duration_in_ms.count();
}

SpSyncOneMsgBinary CNetProtoRecorder::getOrCreateSyncOneMsgBinary(const std::string& folder) {
    auto ite = m_mapSyncOneMsg.find(folder);
    if (ite != m_mapSyncOneMsg.end()) {
        return ite->second;
    }
    auto sp = std::make_shared<CSyncOneMsgBinary>(folder);
    m_mapSyncOneMsg.insert(std::make_pair(folder, sp));
    return sp;
}

SpOneFixedAppendBinary CNetProtoRecorder::getOrCreateOneFixedAppendBinary(const std::string& folder, uint64_t max) {
    auto ite = m_mapSyncFixedAppendBinary.find(folder);
    if (ite != m_mapSyncFixedAppendBinary.end()) {
        return ite->second;
    }
    auto sp = std::make_shared<COneFixedAppendBinary>(folder, max);
    m_mapSyncFixedAppendBinary.insert(std::make_pair(folder, sp));
    return sp;
}

SpSyncMsgLength CNetProtoRecorder::getOrCreateSyncMsgLength(const std::string& folder) {
    auto ite = m_mapSyncMsgLength.find(folder);
    if (ite != m_mapSyncMsgLength.end()) {
        return ite->second;
    }
    auto sp = std::make_shared<CSyncMsgLength>(folder);
    m_mapSyncMsgLength.insert(std::make_pair(folder, sp));
    return sp;
}
